from rest_framework import serializers

#  数据入库，肯定有　ModelSerializer　肯定有模型
from rest_framework.response import Response

from celery_tasks.email.tasks import send_active_email
from goods.models import SKU
from users.models import User, Address
from django_redis import get_redis_connection
from rest_framework_jwt.settings import api_settings
import re


class RegisterCreateUser(serializers.ModelSerializer):
    """
    username(用户名) password(第一次密码) password2(第二次密码) mobile(手机号) sms_code(短信验证码) allow(是否同意协议)
    ModelSerializer 在生成字段的是时候是根据　fields 来生成的
    所有要生产新的字段必须添加到fields里面
    """

    #  User 模型中没有　sms_code password2 allow 这些字段，在返回响应的的时候会进行序列化操作，会一一比对模型中的字段，模型中不存在会报错
    #  所有需要设置只写属性　write_only 属性
    sms_code = serializers.CharField(label='短信验证码', max_length=6, min_length=6, required=True, write_only=True)
    password2 = serializers.CharField(label='确认密码', required=True, write_only=True)
    allow = serializers.CharField(label='是否同意协议', required=True, write_only=True)

    #  设置token字段
    # token = serializers.CharField(label='Token', required=False)

    token = serializers.CharField(label='Token', read_only=True)

    class Meta:
        model = User
        fields = ['username', 'password', 'mobile', 'sms_code', 'password2', 'allow', 'token']
        extra_kwargs = {
            # 'id': {'read_only': True},
            'username': {
                'min_length': 5,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许5-20个字符的用户名',
                    'max_length': '仅允许5-20个字符的用户名',
                }
            },
            'password': {
                'write_only': True,
                'min_length': 8,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许8-20个字符的密码',
                    'max_length': '仅允许8-20个字符的密码',
                }
            }
        }

    def validate_mobile(self, value):
        """校验手机号"""
        if not re.match('1[345789]\d{9}', value):
            raise serializers.ValidationError('手机格式不正确')
        return value

    def validate_allow(self, value):
        """校验是否同意协议"""
        if value == 'false':
            raise serializers.ValidationError('您未同意协议')
        return value

    def validate(self, attrs):
        """校验密码是否一直，和手机验证码是否正确"""
        password = attrs.get('password')
        password2 = attrs.get('password2')
        mobile = attrs.get('mobile')
        msm_code = attrs.get('sms_code')

        #  判断密码是否一致
        if password != password2:
            raise serializers.ValidationError('两次输入的密码不一致')

        # 判断短信验证码是否正确
        #  链接redis
        redis_conn = get_redis_connection('code')
        redis_mobile = redis_conn.get('sms_%s' % mobile)
        # print(redis_mobile)
        #  判断是否过期
        if redis_mobile is None:
            raise serializers.ValidationError('验证码已过期')
        # 判断验证码是否一致
        if msm_code != redis_mobile.decode():
            raise serializers.ValidationError('验证码输入有误')

        return attrs

    def create(self, validated_data):
        """重写提交到数据库的方法，因为有多余的字段不需要保存到数据库"""
        del validated_data['sms_code']
        del validated_data['password2']
        del validated_data['allow']

        users = User.objects.create(**validated_data)

        #  密码采用加密方式储存
        #  调用set_password方法加密
        users.set_password(validated_data['password'])
        users.save()

        #  设置token信息
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
        #  payload可以装载用户信息
        #  利用类的实例化会开辟一个新的空间，在实例化对象添加新的方法不会影响父类的数据
        payload = jwt_payload_handler(users)
        token = jwt_encode_handler(payload)
        users.token = token

        return users


class UserCenterSerializer(serializers.ModelSerializer):
    class Meta:
        """
        用户详细信息序列化器
        """
        model = User
        fields = ('id', 'username', 'mobile', 'email', 'email_active',)


class UserEmailSerializer(serializers.ModelSerializer):
    """
    保存邮箱
    """

    class Meta:
        model = User
        fields = ('email',)

    # 重写更新方法
    def update(self, instance, validated_data):
        email = validated_data['email']
        instance.email = email
        instance.save()

        #  执行发送邮箱
        send_active_email.delay(email=email, user_id=instance.id)
        return instance


"""
创建用户地址序列化器
用户模型中　没有province　city　district这三个属性　所有设置为只读
"""


class AddressSerializer(serializers.ModelSerializer):
    province = serializers.StringRelatedField(read_only=True)
    city = serializers.StringRelatedField(read_only=True)
    district = serializers.StringRelatedField(read_only=True)
    province_id = serializers.IntegerField(label='省ID', required=True)
    city_id = serializers.IntegerField(label='市ID', required=True)
    district_id = serializers.IntegerField(label='区ID', required=True)
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')

    class Meta:
        model = Address
        #  这三个属性都是后期创建完表后生成的，在序列化器中不需要使用
        exclude = ['user', 'is_deleted', 'create_time', 'update_time']

    def create(self, validated_data):
        #  在前端传递过来的数据中，没有用户的id 所以我们重写create方法，添加上用户的id
        validated_data['user'] = self.context['request'].user
        return Address.objects.create(**validated_data)


"""
创建用户收货地址一级视图实现
"""

#
# class AddressSerializer(serializers.ModelSerializer):
#     province = serializers.StringRelatedField(read_only=True)
#     city = serializers.StringRelatedField(read_only=True)
#     district = serializers.StringRelatedField(read_only=True)
#     province_id = serializers.IntegerField(label='省ID', required=True)
#     city_id = serializers.IntegerField(label='市ID', required=True)
#     district_id = serializers.IntegerField(label='区ID', required=True)
#     mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')
#     user_id = serializers.StringRelatedField(read_only=True)
#
#     class Meta:
#         model = Address
#         #  这三个属性都是后期创建完表后生成的，在序列化器中不需要使用
#         exclude = ['is_deleted', 'create_time', 'update_time']

#           def create(self, validated_data):
#               #  在前端传递过来的数据中，没有用户的id 所以我们重写create方法，添加上用户的id
#               # validated_data['user'] = self.context['request'].user
#               return Address.objects.create(**validated_data)


"""
用户更新title信息的序列化器
"""


class UpdateAddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = ('title',)

#
# class UserBrowsingHistorySerializer(serializers.ModelSerializer):
#     """
#     用户历史浏览记录序列化器
#     """
#     sku_id = serializers.IntegerField(label='商品信息', required=True, min_value=1)
#
#     class Meta:
#         model = SKU
#         fields = ['sku_id']


class UserBrowsingHistorySerializer(serializers.ModelSerializer):
    """
    用户历史浏览记录序列化器
    三级视图实现
    """
    sku_id = serializers.IntegerField(label='商品信息', required=True, min_value=1)

    class Meta:
        model = SKU
        fields = ['sku_id']

    def create(self, validated_data):
        """
        需要从写创建方法，应为默认是提交到数据库的
        """
        #  获取当前用户
        user = self.context['request'].user
        # 链接redis
        redis_conn = get_redis_connection('history')
        # 获取商品的id
        sku_id = validated_data.get('sku_id')
        # 先删除当前用户的对应的sku_id，达到去重效果
        redis_conn.lrem('history_%s' % user.id, 0, sku_id)
        # 保存数据到redis中
        redis_conn.lpush('history_%s' % user.id, sku_id)
        # 限制保存数据的条数，这里是五条
        redis_conn.ltrim('history_%s' % user.id, 0, 4)
        #  返回响应
        return validated_data
